using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using Evolution.Engine.Managers;
using Evolution.Engine.SpatialTrees;

namespace Evolution.Engine.Objects
{
    public class ScenePicker : Singleton<ScenePicker>
    {
        private Ray myRay;
        public bool ShowRay;
        public Ray Ray { get { return myRay; } }

        public BaseObject GetClickedModel()
        {
            BaseObject retVal = null;
            int mouseX = InputManager.Instance.CurrentMousePoint.X;
            int mouseY = InputManager.Instance.CurrentMousePoint.Y;

            ShowRay = false;

            Matrix world = CameraManager.Instance.ActiveCamera.World;
            Vector3 nearSource = new Vector3((float)mouseX, (float)mouseY, 0f);
            Vector3 farSource = new Vector3((float)mouseX, (float)mouseY, 1f);

            Vector3 nearPoint = GameEngine.Instance.Device.Viewport.Unproject(nearSource, CameraManager.Instance.ActiveCamera.Projection, CameraManager.Instance.ActiveCamera.View, world);
            Vector3 farPoint = GameEngine.Instance.Device.Viewport.Unproject(farSource, CameraManager.Instance.ActiveCamera.Projection, CameraManager.Instance.ActiveCamera.View, world);

            //Create ray from near clip plane to far clip plane
            Vector3 direction = farPoint - nearPoint;
            direction.Normalize();
            myRay = new Ray(nearPoint, direction);

            retVal = CheckIntersect();

            if (ShowRay)
                RenderRay(nearPoint, farPoint);

            return retVal;
        }

        private BaseObject CheckIntersect()
        {
            foreach (Scenenode node in SceneManager.Instance.CurrentScene.Nodes())
            {
                foreach (BaseObject obj in node.Objects)
                {
                    float? result = myRay.Intersects(obj.BoundingSphere);
                    if (result.HasValue == true)
                        return obj;
                }
            }

            return null;
        }

        private void RenderRay(Vector3 np, Vector3 fp)
        {
            VertexPositionColor[] verts = new VertexPositionColor[2];

            verts[0] = new VertexPositionColor(np, Color.Yellow);
            verts[1] = new VertexPositionColor(fp, Color.Yellow);

            int[] inds = { 0, 1 };

            BasicEffect b = ShaderManager.Instance.GetShader("BasicEffect").Effect as BasicEffect;
            
            b.World = CameraManager.Instance.ActiveCamera.World;
            b.View = CameraManager.Instance.ActiveCamera.View;
            b.Projection = CameraManager.Instance.ActiveCamera.Projection;
            b.DiffuseColor = Color.Yellow.ToVector3();

            b.Begin();
            foreach (EffectPass pass in b.CurrentTechnique.Passes)
            {
                pass.Begin();
                
                GameEngine.Instance.Device.DrawUserIndexedPrimitives<VertexPositionColor>(
                    PrimitiveType.LineList, 
                    verts, 
                    0, 
                    2, 
                    inds, 
                    0, 
                    1
                );

                pass.End();
            }

            b.End();
        }
    }
}
